<?php
/**
 * 本地化类
 * 
 * 配置文件默认存放在config/locale/$locale下，类似于
 * <pre>
 *   /config/locale/zh_CN
 *        config.php
 *        message.php
 * </pre>
 * 
 * 可以在config.php配置文件中添加
 *   $config["key"] = "value";
 * 如果上面的key是headers，如
 * <code>
 *  $config["headers"] = array(
 *		"content-type" => "text/html;charset=utf-8"
 *	); 
 * </code>
 * 则会自动将这些报头发送到浏览器端
 * 
 * 可以在message.php配置文件中添加
 *    $message["key"] = "value";
 * 
 *
 * @package util.core
 * @since 0.2.1
 */
class ILocale extends IObject {
	private $messages = array();
	private $opts = array();
	private $timezone = "";

	private $name;
	private static $defaultName;
	
	/**
	 * 默认参数值
	 * 
	 * 用于fromXxx中的判断
	 *
	 * @since 0.2.1
	 */
	const LOCALE_PARAM = "locale";
	
	/**
	 * 所有已经设置的区域
	 *
	 * @var array
	 * @since 0.2.1
	 */
	private static $locales = array();
	
	/**
	 * Enter description here...
	 *
	 * @var boolean
	 */
	private $isDefault;
	
	/**
	 * 构造器
	 *
	 * @param string $name Locale名称，如en_US,zh_CN
	 * @param boolean $isDefault 是否使用默认的设置
	 * @since 0.2.1
	 */
	public function __construct($name, $isDefault = false) {
		$this->name = $name;
		$this->isDefault = $isDefault;
		
		//配置
		$config = IConfig::opt("@locale.{$name}");
		if (!is_array($config) || empty($config)) {
			$config = IConfig::opt("@locale.tpl");
		}
		
		//timezone
		if (isset($config["timezone"])) {
			$this->timezone = $config["timezone"];
		}
		
		//messages
		$app = IApplication::singleton();
		if (isset($config["message"])) {
			$file = str_replace("%{locale}", $name, $config["message"]);
			$file = $app->relativeFile($file);
			if ($file->exists()) {
				require($file->absPath());
				if (isset($message) && is_array($message)) {
					$this->messages = $message;
				}
			}
		}
		
		//opts
		$app = IApplication::singleton();
		if (isset($config["opt"])) {
			$file = str_replace("%{locale}", $name, $config["opt"]);
			$file = $app->relativeFile($file);
			if ($file->exists()) {
				require($file->absPath());
				if (isset($opt) && is_array($opt)) {
					$this->opts = $opt;
				}
			}
		}
		
		self::$locales[] = $this;
	}
	
	/**
	 * 区域名
	 *
	 * @return string
	 * @since 0.2.1
	 */
	public function name() {
		return $this->name;
	}
	
	public function timezone() {
		return $this->timezone;
	}
	
	/**
	 * 取得配置的头信息
	 *
	 * @return array
	 * @since 0.2.1
	 */
	public function headers() {
		if (isset($this->opts["headers"]) && is_array($this->opts["headers"])) {
			return $this->opts["headers"];
		}
		return array();
	}
	
	/**
	 * 发送头信息
	 *
	 * @return boolean
	 * @since 0.2.1
	 */
	public function sendHeaders() {
		if (headers_sent()) {
			return false;
		}
		foreach ($this->headers() as $name => $content) {
			header($name . ":" . $content);
		}
		return true;
	}
	
	/**
	 * 取得所有消息
	 *
	 * @return array
	 * @since 0.2.1
	 */
	public function messages() {
		return $this->messages;	
	}
	
	/**
	 * 取得所有配置
	 *
	 * @return array
	 * @since 0.2.1
	 */
	public function opts() {
		return $this->opts;
	}
	
	/**
	 * 取得消息
	 *
	 * @param string $key 键
	 * @return string|null
	 * @since 0.2.1
	 */
	public function message($key) {
		return array_key_exists($key, $this->messages)?$this->messages[$key]:null;
	}
	
	/**
	 * 取得配置
	 *
	 * @param string $key 键
	 * @return mixed
	 * @since 0.2.1
	 */
	public function opt($key) {
		return array_key_exists($key, $this->opts)?$this->opts[$key]:null; 
	}
	
	/**
	 * 设置默认的区域
	 *
	 * @param string $name 默认的区域名
	 * @since 0.2.1
	 */
	public static function setDefault($name) {
		self::$defaultName = $name;
	}
	
	/**
	 * 取得看默认的locale
	 *
	 * @return string
	 * @since 0.2.2
	 */
	public static function defaultName() {
		//默认的
		
		if (self::$defaultName == null) {
			self::$defaultName = IConfig::opt("@locale.default_name");
		}
		return self::$defaultName;
	}
	
	/**
	 * 从浏览器取得本地化对象
	 * 
	 * @return ILocale
	 * @since 0.2.1
	 */
	public static function byBrowser($default = null) {
		if ($default != null) {
			self::setDefault($default);
		}
		if (!isset($_SERVER["HTTP_ACCEPT_LANGUAGE"])) {
			return new ILocale(self::defaultName(), true);
		}
		list($langStr) = explode(";", $_SERVER["HTTP_ACCEPT_LANGUAGE"]);
		$langs = explode(",", $langStr);
		if (empty($langs)) {
			if (self::defaultName() == null) {
				throw new IException("failed to get locale from browser");
			}
			else {
				return new ILocale(self::defaultName(), true);
			}
		}
		else {
			$locale = $langs[0];
			if (strstr($locale, "-")) {
				list($lang, $country) = explode("-", $locale);
				$locale = $lang . "_" . strtoupper($country);
			}
			return new ILocale($locale);
		}
	}
	
	/**
	 * 从cookie中获取本地化对象
	 *
	 * @param string $cookieName cookie名
	 * @return ILocale
	 * @since 0.2.1
	 */
	public static function byCookie($cookieName = self::LOCALE_PARAM) {
		$locale = ICookie::get($cookieName);
		if ($locale == null) {
			$locale = self::defaultName();
			return new ILocale($locale, true);
		}
		else {
			return new ILocale($locale);
		}
	}
	
	public static function bySession($sessionName = self::LOCALE_PARAM) {
		$locale = ISession::singleton()->get($sessionName);
		if ($locale == null) {
			$locale = self::defaultName();
			return new ILocale($locale, true);
		}
		else {
			return new ILocale($locale);
		}
	}
	
	/**
	 * 从URL中获取本地化对象
	 *
	 * @param string $paramName 参数名
	 * @return ILocale
	 * @since 0.2.1
	 */
	public static function byUrl($paramName = self::LOCALE_PARAM) {
		$locale = IRequest::singleton()->param($paramName);
		if ($locale == null) {
			$locale = self::defaultName();
			return new ILocale($locale, true);
		}
		else {
			return new ILocale($locale);
		}
	}
	
	/**
	 * 取得当前设置过的区域
	 *
	 * @return array
	 * @since 0.2.1
	 */
	public static function locales() {
		return self::$locales;
	}
	
	/**
	 * 取得当前设置的本地化对象
	 *
	 * @return ILocale
	 * @since 0.2.2
	 */
	public static function current() {
		if (empty(self::$locales)) {
			return self::auto();
		}
		$locales = self::$locales;
		return array_pop($locales);
	}
	
	public function isDefault() {
		return $this->isDefault;
	}
	
	/**
	 * Enter description here...
	 *
	 * @return ILocale
	 */
	public static function auto() {
		$track = IConfig::opt("@locale.track");
		if (!is_array($track) || empty($track)) {
			return new ILocale(self::defaultName());
		}
		
		foreach ($track as $value) {
			if (is_array($value) && isset($value[0])) {
				if ($value[0] == "url") {
					$param = isset($value[1])?$value[1]:self::LOCALE_PARAM;
					$locale = self::byUrl($param);
					if (!$locale->isDefault()) {
						return $locale;
					}
				}
				else if ($value[0] == "cookie") {
					$param = isset($value[1])?$value[1]:self::LOCALE_PARAM;
					$locale = self::byCookie($param);
					if (!$locale->isDefault()) {
						return $locale;
					}
				}
				else if ($value[0] == "session") {
					$param = isset($value[1])?$value[1]:self::LOCALE_PARAM;
					$locale = self::bySession($param);
					if (!$locale->isDefault()) {
						return $locale;
					}
				}
				else if ($value[0] == "browser") {
					$locale = self::byBrowser();
					if (!$locale->isDefault()) {
						return $locale;
					}
				}
			}
			else if (is_string($value) && $value == "browser") {
				$locale = self::byBrowser();
				if (!$locale->isDefault()) {
					return $locale;
				}
			}
		}
		
		return new ILocale(self::defaultName(), true);
	}
}

?>